import json

from django_redis import get_redis_connection
from luckin.common import valid_request_param
from luckin.models import Goods


class ShopCartService:
    _ShopCartKey = "shopCart_%s"
    _ShopCartField = "goods_%s"

    def get(self, request):
        if not valid_request_param(request):
            return False, "参数错误"

        # 拿到redis的链接对象
        redis_conn = get_redis_connection()

        # 这里_q为一个空字典，所有不做处理
        user_id = request.user.id
        redis_h_key = self._ShopCartKey % user_id

        # 因为redis取出的数据为bytes类型，我们将dict的key，value都转为字符串
        redis_result = redis_conn.hgetall(redis_h_key)
        data = dict()
        for key, value in redis_result.items():
            data[str(key, encoding="utf-8")] = str(value, encoding="utf-8")

        # 过滤掉不存在的商品
        # 对于现在不存在的商品，设置一个标识表示该商品是否存在(exist)
        end_data = dict()
        for key, value in data.items():
            goods_id = key.split("_")[-1]
            goods_obj = Goods.objects.filter(pk=goods_id).first()
            goods_info = json.loads(value)
            if not goods_obj:
                goods_info["exist"] = False
            else:
                goods_info["exist"] = True
            end_data[key] = goods_info

        return True, end_data

    def post(self, request):
        # _q:{"goods_id":%s,"goods_count":%s,"price(指单价)":%s,"specification":%s,
        # "temperature":%s,"sugar":%s,"milk":%s,"cream":%s}

        # 对于不同的商品，商品的规格，温度，奶度等等的类型也会不同。
        # 我们需要先拿到该商品的所有的信息，判断各个参数是否合法。
        # 那么对于_q的参数，如果该商品不存在该选项的话，则用0表示
        if not valid_request_param(request):
            return False, "参数错误"

        _q = request.data.get("_q")
        _s = request.data.get("_s")

        param_dict = json.loads(_q)
        goods_id = param_dict.get("goods_id")
        if not goods_id or not isinstance(goods_id, int):
            return False, "参数错误"

        # 判断该商品是否存在
        goods_obj = Goods.objects.filter(pk=goods_id).first()
        if not goods_obj:
            return False, "商品不存在"

        # 检测specification参数
        specification_name = param_dict.get("specification")
        if not specification_name or not isinstance(specification_name, int):
            return False, "参数错误"
        specification_query_set = goods_obj.specification.all().values_list("name", "salt_price")
        specification_list = [i[0] for i in specification_query_set]

        # 如果specification_list有值，并且specification_name不存在specification_list中，则不合法
        if specification_list and specification_name not in specification_list:
            return False, "参数不合法"
        if not specification_list and specification_name != 0:
            return False, "参数错误"

        # 能走到这里，情况分析
        # 1 specification_list存在，并且specification_name在specification_list中，参数合法
        # 2 specification_list不存在，那么specification_name的值只能为0

        # 检测temperature参数
        temperature_name = param_dict.get("temperature")
        if not temperature_name or not isinstance(temperature_name, int):
            return False, "参数错误"
        temperature_query_set = goods_obj.temperature.all().values_list("name")
        temperature_list = [i[0] for i in temperature_query_set]
        if temperature_list and temperature_name not in temperature_list:
            return False, "参数不合法"
        if not temperature_list and temperature_name != 0:
            return False, "参数错误"

        # 检测sugar参数
        sugar_name = param_dict.get("sugar")
        if not sugar_name or not isinstance(sugar_name, int):
            return False, "参数错误"
        sugar_query_set = goods_obj.sugar.all().values_list("name", "price")
        sugar_list = [i[0] for i in sugar_query_set]
        if sugar_list and sugar_name not in sugar_list:
            return False, "参数不合法"
        if not sugar_list and sugar_name != 0:
            return False, "参数错误"

        # 检测milk参数
        milk_name = param_dict.get("milk")
        if not milk_name or not isinstance(milk_name, int):
            return False, "参数错误"
        milk_query_set = goods_obj.milk.all().values_list("name")
        milk_list = [i[0] for i in milk_query_set]
        if milk_list and milk_name not in milk_list:
            return False, "参数不合法"
        if not milk_list and milk_name != 0:
            return False, "参数错误"

        # 检测cream参数
        cream_name = param_dict.get("cream")
        if not cream_name or not isinstance(cream_name, int):
            return False, "参数错误"
        cream_query_set = goods_obj.cream.all().values_list("name", "price")
        cream_list = [i[0] for i in cream_query_set]
        if cream_list and cream_name not in cream_list:
            return False, "参数不合法"
        if not cream_list and cream_name != 0:
            return False, "参数错误"

        # 检验单价是否合法
        # 计算商品单价
        # 目前就specification，sugar，cream
        price = param_dict.get("price")
        if not price:
            return False, "参数错误"
        c_price = 0
        for specification_query in specification_query_set:
            if specification_name == specification_query[0]:
                c_price += specification_query[1]

        for sugar_query in sugar_query_set:
            if sugar_name == sugar_query[0]:
                c_price += sugar_query[1]

        for cream_query in cream_query_set:
            if cream_name == cream_query[0]:
                c_price += cream_query[1]
        if price != c_price:
            return False, "参数不合法"

        # _q的参数合法，在redis中添加该商品
        # 拿到redis的链接对象
        redis_conn = get_redis_connection()
        user_id = request.user.id
        redis_h_field = self._ShopCartField % goods_id
        redis_h_key = self._ShopCartKey % user_id

        redis_conn.hset(redis_h_key, redis_h_field, _q)
        return True, "添加成功"

    def put(self, request):
        # _q : {"command":"increase","goods_id":%s}   # increase 自增   reduction 自减
        # command_list = ["increase","reduction"]
        if not valid_request_param(request):
            return False, "参数错误"

        _q = request.data.get("_q")
        _s = request.data.get("_s")

        param_dict = json.loads(_q)
        command = param_dict.get("command")
        if not command or command not in ["increase", "reduction"]:
            return False, "参数错误"

        # 只对商品数量进行自增，自减操作
        user_id = request.user.id
        goods_id = param_dict.get("goods_id")
        if not goods_id or not isinstance(goods_id, int):
            return False, "参数错误"
        redis_h_field = self._ShopCartField % goods_id
        redis_h_key = self._ShopCartKey % user_id

        # 拿到redis的链接对象
        redis_conn = get_redis_connection()

        # 判断该商品id在购物车中是否存在
        redis_result = redis_conn.hget(redis_h_key, redis_h_field)
        if not redis_result:
            return False, "参数错误"

        try:
            redis_result = str(redis_result, encoding="utf-8")
            goods_dict = json.loads(redis_result)
        except json.decoder.JSONDecodeError:
            return False, "未知操作"

        # 商品存在，数量进行加减操作
        if command == "increase":
            # 自增操作
            goods_dict["goods_count"] += 1
            redis_result = json.dumps(goods_dict)
            redis_conn.hset(redis_h_key, redis_h_field, redis_result)
        else:
            goods_count = goods_dict["goods_count"]
            if goods_count == 1:
                redis_conn.hdel(redis_h_key, redis_h_field)
            else:
                goods_dict["goods_count"] -= 1
                redis_result = json.dumps(goods_dict)
                redis_conn.hset(redis_h_key, redis_h_field, redis_result)
        return True, "更新成功"

    def delete(self, request):
        # _q:{"goods_id":"%s"}
        if not valid_request_param(request):
            return False, "参数错误"

        _q = request.data.get("_q")
        _s = request.data.get("_s")

        param_dict = json.loads(_q)

        user_id = request.user.id
        goods_id = param_dict.get("goods_id")
        if not goods_id or not isinstance(goods_id, int):
            return False, "参数错误"
        redis_h_field = self._ShopCartField % goods_id
        redis_h_key = self._ShopCartKey % user_id

        # 拿到redis的链接对象
        redis_conn = get_redis_connection()
        redis_conn.hdel(redis_h_key, redis_h_field)

        return True, "删除成功"
